package com.apchernykh.rozhlasapp.player.fallback;

import java.io.IOException;

import com.apchernykh.rozhlasapp.utils.ConditionalLog;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnSeekCompleteListener;

public abstract class BaseFallbackPlayer implements
		android.media.MediaPlayer.OnCompletionListener,
		android.media.MediaPlayer.OnPreparedListener,
		android.media.MediaPlayer.OnErrorListener, IFallbackPlayer,
		OnBufferingUpdateListener, OnInfoListener, OnSeekCompleteListener {

	protected boolean mIsPrepared = false;
	protected final Context mContext;
	protected static MediaPlayer mSeparateThreadMediaPlayer = null;

	// Create listeners, and set them to default empty ones.
	static android.media.MediaPlayer.OnErrorListener mOnError = new android.media.MediaPlayer.OnErrorListener() {
		@Override
		public boolean onError(MediaPlayer iPlayer, int iWhat, int iExtra) {
			return false;
		}
	};
	static android.media.MediaPlayer.OnCompletionListener mOnCompletion = new android.media.MediaPlayer.OnCompletionListener() {
		@Override
		public void onCompletion(MediaPlayer iPlayer) {
		}
	};
	static android.media.MediaPlayer.OnPreparedListener mOnPrepared = new android.media.MediaPlayer.OnPreparedListener() {
		@Override
		public void onPrepared(MediaPlayer iPlayer) {
			// TODO Auto-generated method stub

		}
	};

	public BaseFallbackPlayer(Context iContext) {
		mContext = iContext;
	}

	public enum EPlayerState {
		PLAYING, PAUSED, STOPPED, PREBUFFERING, IO_ERROR, ERROR, UNDERRUN, PREPARING
	}

	protected OnBufferingUpdateListener mOnBufferUpdateListener = new OnBufferingUpdateListener() {

		public void onBufferingUpdate(MediaPlayer iPlayer, int iProgressPercent) {
			// By default do nothing
		}
	};

	@Override
	public void setOnBufferingUpdateListener(OnBufferingUpdateListener iListener) {
		mOnBufferUpdateListener = iListener;
	}

	@Override
	public void setOnErrorListener(
			android.media.MediaPlayer.OnErrorListener iMediaPlayerWrapper) {
		mOnError = iMediaPlayerWrapper;

	}

	@Override
	public void setOnPreparedListener(
			android.media.MediaPlayer.OnPreparedListener iMediaPlayerWrapper) {
		mOnPrepared = iMediaPlayerWrapper;

	}

	@Override
	public void setOnCompletionListener(
			android.media.MediaPlayer.OnCompletionListener mediaPlayerWrapper) {
		mOnCompletion = mediaPlayerWrapper;
	}

	protected void resetMediaPlayer(String iURL) throws IOException {
		synchronized (this) {
			mSeparateThreadMediaPlayer = new MediaPlayer();
			mSeparateThreadMediaPlayer.setOnBufferingUpdateListener(this);
			mSeparateThreadMediaPlayer.setOnCompletionListener(this);
			mSeparateThreadMediaPlayer.setOnErrorListener(this);
			mSeparateThreadMediaPlayer.setOnInfoListener(this);
			mSeparateThreadMediaPlayer.setOnPreparedListener(this);
			mSeparateThreadMediaPlayer.setOnSeekCompleteListener(this);
			mSeparateThreadMediaPlayer.setDataSource(iURL);
			mSeparateThreadMediaPlayer
					.setAudioStreamType(AudioManager.STREAM_MUSIC);
			ConditionalLog.e("reset player to "
					+ String.valueOf(mSeparateThreadMediaPlayer));
		}
	}

	@Override
	public boolean onError(MediaPlayer iPlayer, int iWhat, int iExtra) {
		ConditionalLog.e(" playbackErrorListener " + String.valueOf(iWhat) + ":"
				+ String.valueOf(iExtra));
		if (iPlayer != mSeparateThreadMediaPlayer) {
			ConditionalLog.e("received playback error from wrong instance " + String.valueOf(iPlayer)
					+ " instead of "
					+ String.valueOf(mSeparateThreadMediaPlayer));
			return false;
		} else {
			mIsPrepared = false;
			dispose();
			return mOnError.onError(iPlayer, iWhat, iExtra);
		}
	}

	@Override
	public void onCompletion(MediaPlayer iPlayer) {
		if (iPlayer != mSeparateThreadMediaPlayer) {
			ConditionalLog.e(
					this.toString(),
					"received onCompletion from wrong instance "
							+ String.valueOf(iPlayer) + " instead of "
							+ String.valueOf(mSeparateThreadMediaPlayer));
		} else {
			mOnCompletion.onCompletion(iPlayer);
		}
	}

	@Override
	public void onPrepared(MediaPlayer iPlayer) {
		if (iPlayer != mSeparateThreadMediaPlayer) {
			ConditionalLog.e("received onPrepared from wrong instance "
							+ String.valueOf(iPlayer) + " instead of "
							+ String.valueOf(mSeparateThreadMediaPlayer));
		} else {
			ConditionalLog.e(" onPrepared "+ String.valueOf(iPlayer == mSeparateThreadMediaPlayer));
			synchronized (this) {
				if (mSeparateThreadMediaPlayer != null) {
					mIsPrepared = true;
					mSeparateThreadMediaPlayer.start();
				}
			}
			mOnPrepared.onPrepared(iPlayer);
		}
	}

	@Override
	public void onBufferingUpdate(MediaPlayer iPlayer, int iProgressPercentage) {
		ConditionalLog.e(" onBufferUpdate " + String.valueOf(iProgressPercentage) + " "
				+ String.valueOf(iPlayer == mSeparateThreadMediaPlayer));

	}

	@Override
	public boolean onInfo(MediaPlayer iPlayer, int iWhat, int iExtra) {
		ConditionalLog.e(" onInfo " + String.valueOf(iWhat) + " "
				+ String.valueOf(iPlayer == mSeparateThreadMediaPlayer));
		return false;
	}

	@Override
	public void onSeekComplete(MediaPlayer iPlayer) {
		ConditionalLog.e(" onSeekComplete " + " "
				+ String.valueOf(iPlayer == mSeparateThreadMediaPlayer));

	}

	@Override
	public void dispose() {
		if (mSeparateThreadMediaPlayer != null) {
			mSeparateThreadMediaPlayer.release();
			mSeparateThreadMediaPlayer = null;
			ConditionalLog.e("reset player to "
					+ String.valueOf(mSeparateThreadMediaPlayer));
		}
	}
}
